/* 
 * 本文件将照片入库
 */
var config = require("./config.json");
var Sequelize = require("sequelize");
var sequelize = new Sequelize(config.database, config.userName, config.password, {
	dialect: config.dialect,
	logging: false
});
var Polylines = sequelize.import("./models/polyline");
var Pictures = sequelize.import("./models/picture");
sequelize.sync({
	force: false
});
// 遍历所有照片文件
var fs = require("fs");
var im = require("imagemagick");
var path = "./upload"
fs.readdir(path, function (err, dirs) {
	if (err)
		return;
	dirs.reduce(function (prev, curr, index) {
		return prev.then(function () {
			return new Promise(function (resolve, reject) {
				fs.readdir(path + "/" + curr, function (err, files) {
					if (err)
						reject(err);
					else
						resolve(files.reduce(function (previous, current, index) {
							return previous.then(function (value) {
								return new Promise(function (resolve, reject) {
									if (current.indexOf(".txt") === -1)
										im.readMetadata(path + "/" + curr + "/" + current, function (err, metadata) {
											console.log(index);
											if (err)
												reject(err);
											else {
												// 提取经纬度
												var a = extract(metadata.exif.gpsLatitude);
												var b = extract(metadata.exif.gpsLongitude);
												if (a >= -90 && a <= 90 && b >= -180 && b <= 180) {
													value.push({
														latitude: a,
														longitude: b,
														fileName: path + "/" + curr + "/" + current
													});
												}
												resolve(value);
											}
										});
									else
										resolve(value);
								});
							});
						}, Promise.resolve([])).then(function (value) {
							// 存储到 [Polylines] 中
							return Polylines.create({
								name: curr,
								geometry: toGeoJson(value)
							}).then(function (instance) {
								return {
									instance: instance,
									value: value
								};
							});
						}).then(function (result) {
							// 存储到 [Pictures] 中
							return result.value.reduce(function (previous, current) {
								return previous.then(function () {
									current.polyline = result.instance.id;
									return Pictures.create(current);
								});
							}, Promise.resolve({}));
						}));
				});
			});
		}, function (error) {
			return Promise.reject(error);
		});
	}, Promise.resolve(null)).then(function () {
		console.log("Completed.");
		sequelize.close();
	}, function (error) {
		console.log(error.message);
		sequelize.close();
	});
});

// 从 Exif 信息中提取出经度或纬度
// 参数 value 为符合 Exif 标准的字符串
// 结果为十进制度
var extract = function (value) {
	var coefficients = [1.0, 60.0, 3600.0];
	return value.split(",").reduce(function (previous, current, index) {
		var numbers = current.split("/");
		return previous + parseFloat(numbers[0]) / parseFloat(numbers[1]) / coefficients[index];
	}, 0.0);
};

// 将多段线转换成 GeoJson 格式的字符串
// 参数 value 为二维数组，表示多段线每个点的坐标：[[lng, lat], [lng, lat]...]
// 结果为字符串
var toGeoJson = function (value) {
	var obj = {
		type: "LineString",
		coordinates: []
	};
	value.forEach(function (value) {
		obj.coordinates.push([value.longitude, value.latitude]);
	});
	return JSON.stringify(obj);
};

// 将城市坐标转换成大地坐标
// 参数 x 和 y 是城市坐标
// 结果包含 lat 和 lng 两个属性，是转换后的大地坐标
var XYtoBL = function (x, y) {
    var A11 = 0.999999999800519;
    var A12 = -1.99740336119673E-05;
    var X0 = 3457078.92290726;
    var Y0 = 45.7931310227507;
    var K = 0.999997083735963;
    var X84 = K * (A11 * x + A12 * y) + X0;
    var Y84 = K * (-A12 * x + A11 * y) + Y0;

	var a = 6378137;
    var Alfa = 1.0 / 298.257223563;
    var B = a * (1 - Alfa);
    var e1 = Math.sqrt((a / B) * (a / B) - 1);
    var e = Math.sqrt(1 - (B / a) * (B / a));

    var m0 = a * (1.0 - e * e);
    var m2 = 3.0 * e * e * m0 / 2.0;
    var m4 = 5.0 * e * e * m2 / 4.0;
    var m6 = 7.0 * e * e * m4 / 6.0;
    var m8 = 9.0 * e * e * m6 / 8.0;

    var a0 = m0 + m2 / 2.0 + 3.0 * m4 / 8.0 + 5.0 * m6 / 16.0 + 35.0 * m8 / 128.0;
    var a2 = m2 / 2.0 + m4 / 2.0 + 15.0 * m6 / 32.0 + 7.0 * m8 / 16.0;
    var a4 = m4 / 8.0 + 3.0 * m6 / 16.0 + 7.0 * m8 / 32.0;
    var a6 = m6 / 32.0 + m8 / 16.0;
	var a8 = m8 / 128.0;

    var X = X84;
    var Y = Y84;
    
    var Bf0 = X / a0;
	var dB;
    
	do {
       var sinBf = Math.sin(Bf0);
       var cosBf = Math.cos(Bf0);
       var FBf = -sinBf * cosBf * ((a2 - a4 + a6) + (2.0 * a4 - 16.0 * a6 / 3.0) * sinBf * sinBf + (16.0 / 3.0) * a6 * (sinBf * sinBf * sinBf * sinBf));
       var Bf1 = (X - FBf) / a0;
       dB = Bf1 - Bf0;
       Bf0 = Bf1;
	} while (Math.abs(dB) > 0.0000000001)
     
    var bf = Bf1;
 
    var c = a * (a / B);
    var v = Math.sqrt(1 + e1 * e1 * Math.cos(bf) * Math.cos(bf));
    var Nf = c / v;
    var Mf = c / (v * v * v);
    var tf = Math.sin(bf) / Math.cos(bf);
    var itaf = e1 * Math.cos(bf);
 
    var detaB = tf * Y * Y / (2 * Mf * Nf) - tf * (5 + 3 * tf * tf + itaf * itaf - 9 * tf * tf * itaf * itaf) * Y * Y * Y * Y / (24 * Mf * Nf * Nf * Nf) + (61 + 90 * tf * tf + 45 * tf * tf * tf * tf) * Y * Y * Y * Y * Y * Y / (720 * Mf * Nf * Nf * Nf * Nf * Nf);
    var detaL = Y / (Nf * Math.cos(bf) + (1 + 2 * tf * tf + itaf * itaf) * Math.cos(bf) * Y * Y / (6 * Nf)) + (5 + 44 * tf * tf + 32 * tf * tf * tf * tf - 2 * itaf * itaf - 16 * itaf * itaf * tf * tf) / (360 * Nf * Nf * Nf * Mf * Mf * Math.cos(bf));
  
    var Lo = 121.46667 * Math.PI / 180;
    return {
		lat: (bf - detaB) * 180 / Math.PI,
		lng: (Lo + detaL) * 180 / Math.PI
	} ;
}